package com.xiejun;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ServletContainer {
    private static ServletContainer instance = new ServletContainer();
    private Map<String, Class<? extends HttpServlet>> urlMappings = new HashMap<>();

    private ServletContainer() {
        scanAndRegisterServlets();
    }

    public static ServletContainer getInstance() {
        return instance;
    }

    public HttpServlet getServlet(String url) {
        Class<? extends HttpServlet> servletClass = urlMappings.get(url);
        if (servletClass != null) {
            try {
                return servletClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException("Failed to instantiate servlet for URL: " + url, e);
            }
        }
        return null;
    }

    private void scanAndRegisterServlets() {
        try {
            // 获取classpath
            String classpath = System.getProperty("java.class.path");
            String[] paths = classpath.split(System.getProperty("path.separator"));

            for (String path : paths) {
                // 只扫描项目相关的jar包和目录，避免扫描系统jar包
                if (path.contains("xiejun-tomcat") || path.contains("target") || path.contains("classes")) {
                    if (path.endsWith(".jar")) {
                        scanJarFile(path);
                    } else {
                        scanDirectory(path);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("Error scanning servlets", e);
        }
    }

    private void scanJarFile(String jarPath) throws IOException {
        try {
            JarFile jarFile = new JarFile(jarPath);
            Enumeration<JarEntry> entries = jarFile.entries();

            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                String entryName = entry.getName();

                if (entryName.endsWith(".class")) {
                    String className = entryName.replace('/', '.').substring(0, entryName.length() - 6);
                    checkAndRegisterServlet(className);
                }
            }
            jarFile.close();
        } catch (IOException e) {
            // 忽略无法读取的jar文件
            System.err.println("Could not scan jar file: " + jarPath);
        }
    }

    private void scanDirectory(String directoryPath) {
        File directory = new File(directoryPath);
        if (directory.isDirectory()) {
            scanClassesInDirectory(directory, directoryPath);
        }
    }

    private void scanClassesInDirectory(File directory, String basePackagePath) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    scanClassesInDirectory(file, basePackagePath);
                } else if (file.getName().endsWith(".class")) {
                    String absolutePath = file.getAbsolutePath();
                    String relativePath = absolutePath.substring(basePackagePath.length() + 1);
                    String className = relativePath.replace(File.separatorChar, '.');
                    className = className.substring(0, className.length() - 6); // Remove .class
                    checkAndRegisterServlet(className);
                }
            }
        }
    }

    private void checkAndRegisterServlet(String className) {
        try {
            Class<?> clazz = Class.forName(className);
            if (HttpServlet.class.isAssignableFrom(clazz)) {
                WebServlet annotation = clazz.getAnnotation(WebServlet.class);
                if (annotation != null) {
                    Class<? extends HttpServlet> servletClass = (Class<? extends HttpServlet>) clazz;
                    String[] urlPatterns = annotation.urlPatterns();
                    for (String urlPattern : urlPatterns) {
                        urlMappings.put(urlPattern, servletClass);
                        System.out.println("Registered servlet " + className + " for URL pattern: " + urlPattern);
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            // Ignore classes that cannot be loaded
        } catch (Exception e) {
            // Ignore other exceptions during scanning
        }
    }
}